package com.api.syh56.shengyunhui.service.impl;

import cn.hutool.core.date.DateTime;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.teautil.models.RuntimeOptions;
import com.api.syh56.shengyunhui.common.Constants;
import com.api.syh56.shengyunhui.entity.*;
import com.api.syh56.shengyunhui.eunm.SystemMessageEunm;
import com.api.syh56.shengyunhui.mapper.SystemMessageMapper;
import com.api.syh56.shengyunhui.properties.AliSmsProperties;
import com.api.syh56.shengyunhui.service.*;
import com.api.syh56.shengyunhui.util.AliSpeechUtil;
import com.api.syh56.shengyunhui.util.RedisUtil;
import com.api.syh56.shengyunhui.websocket.ChatServer;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Service
@Slf4j
public class SystemMessageServiceImpl extends ServiceImpl<SystemMessageMapper, SystemMessage> implements SystemMessageService {


    @Autowired
    private AliSpeechUtil aliSpeechUtil;

    @Autowired
    private ChatServer chatServer;

    @Autowired
    private TmpAddressService tmpAddressService;

    @Autowired
    private RoutesServiceImpl routesService;

    @Autowired
    private GoodsService goodsService;
    @Autowired
    private WayBillServiceImpl wayBillService;

    @Autowired
    private UserService userService;


    @Autowired
    private JpushService jpushService;


    @Autowired
    private SystemMessageMapper systemMessageMapper;

    @Autowired
    private QuoteService quoteService;

    /**
     * 新消息（生成语音，websocket通知客户端）
     * @param senderId
     * @param receiverId
     * @param systemMessageEunm
     * @param message
     * @param waybillId
     */
    public void newMessage(Long senderId, Long receiverId, SystemMessageEunm systemMessageEunm, String message, Long waybillId) {

        //将新消息插入数据库
        SystemMessage systemMessage = SystemMessage.builder()
                        .senderId(senderId)
                        .receiverId(receiverId)
                        .type(systemMessageEunm.getType())
                        .title(systemMessageEunm.getTitle())
                        .content(message)
                        .isRead(false)
                        .waybillId(waybillId)
                        .build();
        save(systemMessage);



        User receiverUser = userService.getById(receiverId);
        String remotePath = "";

        //如果用户存在（可能注销或删除）
        if (Objects.nonNull(receiverUser)){
            if (receiverUser.getVoiceSetting()){
                //如果用户设置了语音播报，则调用阿里云接口生成语音文件
                LocalDate now = LocalDate.now();
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
                String formattedDate = now.format(formatter);
                // 使用格式化的日期构造新文件名称
                String audioFileName = UUID.randomUUID().toString() + ".mp3";
                String path = "D:\\wwwroot\\www.syh56.com\\wwwroot\\audio\\"+formattedDate+"\\"+audioFileName;
                remotePath = "https://www.syh56.com/audio/"+formattedDate+"/"+audioFileName;
                aliSpeechUtil.textToSpeech(message,path);
            }

//        Map<String,Object> map = new HashMap<>();
//        map.put("url",remotePath);
//        String jsonString = JSON.toJSONString(map);
            //websocket推送消息 发送语音文件远程地址
            chatServer.sendToUser(receiverId,remotePath);
        }


        //极光消息推送
        jpushService.pushMessageToUserId(receiverId,systemMessageEunm.getTitle(),message);


    }

    public void newMessageWithSpeechRemotePath(Long senderId, Long receiverId, SystemMessageEunm systemMessageEunm, String message, Long waybillId,String remotePath) {

        //将新消息插入数据库
        SystemMessage systemMessage = SystemMessage.builder()
                .senderId(senderId)
                .receiverId(receiverId)
                .type(systemMessageEunm.getType())
                .title(systemMessageEunm.getTitle())
                .content(message)
                .isRead(false)
                .waybillId(waybillId)
                .build();
        save(systemMessage);

        User receiverUser = userService.getById(receiverId);

        //如果用户存在（可能注销或删除）
        if (Objects.nonNull(receiverUser)){
            if (receiverUser.getVoiceSetting()){
                //websocket推送消息 发送语音文件远程地址
                chatServer.sendToUser(receiverId,remotePath);
            }else {
                //websocket推送消息 发送空白字符串远程地址（前端就不会播放语音）
                chatServer.sendToUser(receiverId,"");
            }
        }
        //极光消息推送
        jpushService.pushMessageToUserId(receiverId,systemMessageEunm.getTitle(),message);

    }


    public void deleteMessage(Long id) {
        removeById(id);
    }

    public SystemMessage readMessage(Long id){
        SystemMessage byId = getById(id);

        //如果已经读过，则不操作
        //如果没读过，则设置为已读
        if (byId.getIsRead().equals(false)){
            byId.setIsRead(true);
            updateById(byId);
        }
        return byId;
    }

    /**
     * 一键已读
     */
    @Override
    public void readAllMessage(Long receiverId) {
        QueryWrapper<SystemMessage> systemMessageQueryWrapper = new QueryWrapper<>();
        systemMessageQueryWrapper.lambda()
                .eq(SystemMessage::getReceiverId,receiverId)
                .ne(SystemMessage::getIsRead,true);
        List<SystemMessage> list = list(systemMessageQueryWrapper);
        for (SystemMessage message : list){
            message.setIsRead(true);
            updateById(message);
        }
    }

    @Override
    public Page<SystemMessage> getAllMessage(Long receiverId, Integer pageNum, Integer pageSize) {
        QueryWrapper<SystemMessage> systemMessageQueryWrapper = new QueryWrapper<>();
        systemMessageQueryWrapper.lambda()
                .eq(SystemMessage::getReceiverId,receiverId)
                .orderByDesc(SystemMessage::getCreationTime);
        Page<SystemMessage> systemMessagePage = new Page<>(pageNum, pageSize);
        Page<SystemMessage> page = page(systemMessagePage, systemMessageQueryWrapper);
        return page;
    }

    public Page<SystemMessage> getReceivedMessageNotRead(Long receiverId, Integer pageNum, Integer pageSize){
        QueryWrapper<SystemMessage> systemMessageQueryWrapper = new QueryWrapper<>();
        systemMessageQueryWrapper.lambda()
                .eq(SystemMessage::getReceiverId,receiverId)
                .eq(SystemMessage::getIsRead,false)
                .orderByDesc(SystemMessage::getCreationTime);
        Page<SystemMessage> systemMessagePage = new Page<>(pageNum, pageSize);
        Page<SystemMessage> page = page(systemMessagePage, systemMessageQueryWrapper);
        return page;
    }

    public Page<SystemMessage> getReceivedMessageisRead(Long receiverId, Integer pageNum, Integer pageSize){
        QueryWrapper<SystemMessage> systemMessageQueryWrapper = new QueryWrapper<>();
        systemMessageQueryWrapper.lambda()
                .eq(SystemMessage::getReceiverId,receiverId)
                .eq(SystemMessage::getIsRead,true)
                .orderByDesc(SystemMessage::getCreationTime);
        Page<SystemMessage> systemMessagePage = new Page<>(pageNum, pageSize);
        Page<SystemMessage> page = page(systemMessagePage, systemMessageQueryWrapper);
        return page;
    }

    /**
     * 发送消息给司机，当发布货源收发地与常用路线匹配时
     * @param waybill
     */

    @Override
    public void SendMessageToDriverWhenSameAddress(Waybill waybill) {
        log.info("SendMessageToDriverWhenSameAddress");
        System.out.println(waybill);

        Long shipAddressId = waybill.getShipAddressId();
        Long receiveAddressId = waybill.getReceiveAddressId();
        Long shiperId = waybill.getShiperId();
        User shiper = userService.selectById(shiperId);
        TmpAddress shipAddress = tmpAddressService.getById(shipAddressId);
        TmpAddress receiveAddress = tmpAddressService.getById(receiveAddressId);
        Long shipAddressAdCode = shipAddress.getAdCode();
        Long receiveAddressAdCode = receiveAddress.getAdCode();

        System.out.println("shipAddressAdCode:"+ shipAddressAdCode);
        System.out.println("receiveAddressAdCode:"+ receiveAddressAdCode);

        Goods goods = goodsService.getById(waybill.getGoodsId());
        String message =
                "省运慧提醒您，从"
//                        + shipAddress.getProvince()
                        + shipAddress.getCity()
                + "到"
//                        + receiveAddress.getProvince()
                        +  receiveAddress.getCity()
                + "有" + goods.getGoodsWeight()+ "吨"
//                        + goods.getGoodsSize() + "立方米"
                        + goods.getGoodsName() +  "，请注意查收";

        //如果用户设置了语音播报，则调用阿里云接口生成语音文件
        LocalDate now = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        String formattedDate = now.format(formatter);
        // 使用格式化的日期构造新文件名称
        String audioFileName = UUID.randomUUID().toString() + ".mp3";
        String path = "D:\\wwwroot\\www.syh56.com\\wwwroot\\audio\\"+formattedDate+"\\"+audioFileName;
        String remotePath = "https://www.syh56.com/audio/"+formattedDate+"/"+audioFileName;
        aliSpeechUtil.textToSpeech(message,path);


        QueryWrapper<Routes> routesQueryWrapper = new QueryWrapper<>();
        routesQueryWrapper.lambda()
                .eq(Routes::getDstAdCode,receiveAddressAdCode)
                .eq(Routes::getOriAdCode,shipAddressAdCode);
        List<Routes> SameRoutes = routesService.list(routesQueryWrapper);
        SameRoutes.forEach(routes -> {
            Long driverId = routes.getUid();
            System.out.println("\n\n\ndriverId:\n\n\n\n\n"+ driverId);
            User driver = userService.getById(driverId);
            //发送消息给 收发地点匹配的专线用户（包含websocket发送 语音远程地址）
            newMessageWithSpeechRemotePath(waybill.getShiperId(), driverId,SystemMessageEunm.GOODS, message, waybill.getId(),remotePath);
//            if (driver.getRoles() == Constants.Role.DRIVER){
//                //调用阿里云接口，发送语音播报
//                sendSmsMessage(driver.getUserName(),shipAddress.getCity(),receiveAddress.getCity(),"匹配"
//                        ,shiper.getUserName());
//            }
        });


    }

    /**
     * 超时发送
     * @param waybill
     */
    @Override
    public void SendMessageToDriverTimeOut(Waybill waybill) {
        System.out.println(waybill);

        Long shipAddressId = waybill.getShipAddressId();
        Long receiveAddressId = waybill.getReceiveAddressId();
        TmpAddress shipAddress = tmpAddressService.getById(shipAddressId);
        TmpAddress receiveAddress = tmpAddressService.getById(receiveAddressId);
        Long shipAddressAdCode = shipAddress.getAdCode();
        Long receiveAddressAdCode = receiveAddress.getAdCode();

        System.out.println("shipAddressAdCode:"+ shipAddressAdCode);
        System.out.println("receiveAddressAdCode:"+ receiveAddressAdCode);

        Goods goods = goodsService.getById(waybill.getGoodsId());
        String message =
                "省运慧提醒您，从"
//                        + shipAddress.getProvince()
                        + shipAddress.getCity()
                        + "到"
//                        + receiveAddress.getProvince()
                        +  receiveAddress.getCity()
                        + "有" + goods.getGoodsWeight()+ "吨"
//                        + goods.getGoodsSize() + "立方米"
                        + goods.getGoodsName() +  "，请注意查收";

        //如果用户设置了语音播报，则调用阿里云接口生成语音文件
        LocalDate now = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        String formattedDate = now.format(formatter);
        // 使用格式化的日期构造新文件名称
        String audioFileName = UUID.randomUUID().toString() + ".mp3";
        String path = "D:\\wwwroot\\www.syh56.com\\wwwroot\\audio\\"+formattedDate+"\\"+audioFileName;
        String remotePath = "https://www.syh56.com/audio/"+formattedDate+"/"+audioFileName;
        aliSpeechUtil.textToSpeech(message,path);

        QueryWrapper<Routes> routesQueryWrapper = new QueryWrapper<>();
        routesQueryWrapper.lambda()
                .eq(Routes::getDstAdCode,receiveAddressAdCode)
                .eq(Routes::getOriAdCode,shipAddressAdCode);
        List<Routes> SameRoutes = routesService.list(routesQueryWrapper);
        SameRoutes.forEach(routes -> {
            Long driverId = routes.getUid();
            System.out.println("\n\n\ndriverId:\n\n\n\n\n"+ driverId);
            User driver = userService.getById(driverId);
            QueryWrapper<Quote> wrapper = new QueryWrapper<>();
            wrapper.lambda()
                            .eq(Quote::getWaybillId,waybill.getId())
                            .eq(Quote::getDriverId,driverId);
            Quote quote = quoteService.getOne(wrapper);
            if (Objects.isNull(quote)) {
                //发送消息给 收发地点匹配的专线用户（包含websocket发送 语音远程地址）
                newMessageWithSpeechRemotePath(waybill.getShiperId(), driverId,SystemMessageEunm.GOODS, message, waybill.getId(),remotePath);
            }
            });
    }

    /**
     * 专线修改报价后，发消息给货主
     * @param
     * @param quote
     */
    @Override
    public void SendMessageToUpdateQuote(Waybill waybill, Quote quote) {
        log.info("SendMessageToUpdateQuote");
        System.out.println(quote);
        String message = "省运慧提醒您，您有一笔订单报价已被修改";
        newMessage(quote.getDriverId(),quote.getShiperId(),SystemMessageEunm.UPDATE_QUOTE,message, waybill.getId());
    }


    /**
     * 司机报价后，发送消息给货主
     */
    public void SendMessageToShiperWhenDriverQuote(Waybill waybill, Quote quote){
        log.info("SendMessageToShiperWhenDriverQuote");
        System.out.println(waybill);
        System.out.println(quote);
//        BigDecimal quoteOfferPrice = quote.getOfferPrice();
//        //计算平台服务费5%
//        BigDecimal fivePercent = quoteOfferPrice.multiply(new BigDecimal("0.05"));
//        // 向上取整
//        BigDecimal roundedUp = fivePercent.setScale(2,BigDecimal.ROUND_UP);
//        BigDecimal limitAmountRoundedUp = limitAmount(roundedUp);
//        BigDecimal offerAll = quoteOfferPrice.add(limitAmountRoundedUp);
        String message ="省运慧提醒您，您的订单已有专线报价，请及时确认";
//                "省运慧提醒你，您的订单已有专线报价"+offerAll+"元，请及时确认";

        newMessage(quote.getDriverId(),quote.getShiperId(),SystemMessageEunm.QUOTE,message,waybill.getId());
    }

    @Override
    public void SendMessageToDriverWhenQuotePaid(Quote quote) {
        log.info("SendMessageToDriverWhenQuotePaid");
        System.out.println(quote);
        String message = "省运慧提醒您，您的报价已被确认，请在约定时间内完成运单";
        newMessage(quote.getShiperId(), quote.getDriverId(), SystemMessageEunm.DEPOSIT,message,quote.getWaybillId());
    }


    /**
     * 司机运输完成后，等待结算，发送消息给货主
     */
    public void SendMessageToShiperWhenWaybillFinish(Waybill waybill){
        log.info("SendMessageToShiperWhenWaybillFinish");
        System.out.println(waybill);
        String message = "省运慧提醒您，您的运单已完成，请及时结算";
        newMessage(waybill.getDriverId(),waybill.getShiperId(),SystemMessageEunm.SETTLE,message,waybill.getId());
    }

    @Override
    public void SendMessageToDriverWhenTimeout(Waybill waybill) {
        log.info("SendMessageToDriverWhenTimeout");
        System.out.println(waybill);
        String message = "省运慧提醒您，请及时将所接运单装货发车";
        newMessage(waybill.getShiperId(), waybill.getDriverId(), SystemMessageEunm.TIMEOUT, message, waybill.getId());
    }


    @Autowired
    Client client;

    @Autowired
    private AliSmsProperties aliSmsProperties;

    @Override
    public void sendSmsMessage(String phoneNumber, String address1, String address2, String status, String phone, String car) {



        log.info("sendSmsMessage:{}",phoneNumber);

        // 定义签名名称变量
        String signName = aliSmsProperties.getSignName();
        // 定义模板代码变量
        String templateCode = "SMS_471855186";

        // 定义模板参数变量，假设paramCode是你要发送的验证码
//        Random random = new Random();
//        StringBuilder codeBuilder = new StringBuilder();
//        // 生成六位随机数验证码
//        for (int i = 0; i < 6; i++) {
//            codeBuilder.append(random.nextInt(10)); // 生成0到9之间的随机数
//        }
//        String paramCode = codeBuilder.toString();

        Map<String, String> paramMap = new HashMap<String, String>();

        paramMap.put("address1",address1);
        paramMap.put("address2",address2);
        paramMap.put("status",status);
        paramMap.put("phone",phone);
        paramMap.put("car",car);
        String json = new Gson().toJson(paramMap);
        System.out.println("\n\n\njson:"+json);


        // 创建SendSmsRequest对象并设置变量值
        SendSmsRequest sendSmsRequest = new SendSmsRequest()
                .setPhoneNumbers(phoneNumber)
                .setSignName(signName)
                .setTemplateCode(templateCode)
                .setTemplateParam(json);
        SendSmsResponse sendSmsResponse = null;
        try {
            sendSmsResponse = client.sendSmsWithOptions(sendSmsRequest, new RuntimeOptions());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        System.out.println(sendSmsResponse.getBody().getCode());
        if("OK".equals(sendSmsResponse.getBody().getCode())){
            log.info(phoneNumber+"发送成功");
        }
    }

    @Override
    public void sendSmsShipMessage(String phoneNumber,String WaybillNum, String address1, String address2, String status, String phone, String car) {

        log.info("sendSmsShipMessage:{}",WaybillNum);
        // 定义签名名称变量
        String signName = aliSmsProperties.getSignName();
        // 定义模板代码变量
        String templateCode = aliSmsProperties.getShipTemplateCode();
        Map<String, String> paramMap = new HashMap<String, String>();
        paramMap.put("waybillNum",WaybillNum);
        paramMap.put("address1",address1);
        paramMap.put("address2",address2);
        paramMap.put("status",status);
        paramMap.put("phone",phone);
        paramMap.put("car",car);
        String json = new Gson().toJson(paramMap);
        System.out.println("\n\n\njson:"+json);
        // 创建SendSmsRequest对象并设置变量值
        SendSmsRequest sendSmsRequest = new SendSmsRequest()
                .setPhoneNumbers(phoneNumber)
                .setSignName(signName)
                .setTemplateCode(templateCode)
                .setTemplateParam(json);
        SendSmsResponse sendSmsResponse = null;
        try {
            sendSmsResponse = client.sendSmsWithOptions(sendSmsRequest, new RuntimeOptions());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        System.out.println(sendSmsResponse.getBody().getCode());
        if("OK".equals(sendSmsResponse.getBody().getCode())){
            log.info(phoneNumber+"发送成功");
        }
    }

    @Override
    public void sendSmsReceiveMessage(String phoneNumber, String WaybillNum, String address1, String address2, String status, String car) {

        log.info("sendSmsReceiveMessage:{}",WaybillNum);
        // 定义签名名称变量
        String signName = aliSmsProperties.getSignName();
        // 定义模板代码变量
        String templateCode = aliSmsProperties.getReceiveTemplateCode();
        Map<String, String> paramMap = new HashMap<String, String>();
        paramMap.put("waybillNum",WaybillNum);
        paramMap.put("address1",address1);
        paramMap.put("address2",address2);
        paramMap.put("status",status);
        paramMap.put("car",car);
        String json = new Gson().toJson(paramMap);
        System.out.println("\n\n\njson:"+json);
        // 创建SendSmsRequest对象并设置变量值
        SendSmsRequest sendSmsRequest = new SendSmsRequest()
                .setPhoneNumbers(phoneNumber)
                .setSignName(signName)
                .setTemplateCode(templateCode)
                .setTemplateParam(json);

        SendSmsResponse sendSmsResponse = null;
        try {
            sendSmsResponse = client.sendSmsWithOptions(sendSmsRequest, new RuntimeOptions());
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
        System.out.println(sendSmsResponse.getBody().getCode());
        if("OK".equals(sendSmsResponse.getBody().getCode())){
            log.info(phoneNumber+"发送成功");
        }
    }

    @Override
    public void sendWithDrawSuccess(Long uid, String time) {
        System.out.println("调用提现成功接口");
        User user = userService.getById(uid);
        String phoneNumber = user.getUserName();
        String signName = aliSmsProperties.getSignName();
        String withDrawSuccessCode = aliSmsProperties.getWithDrawSuccessCode();
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("time",time);
        String json = new Gson().toJson(paramMap);
        SendSmsRequest sendSmsRequest = new SendSmsRequest()
                .setPhoneNumbers(phoneNumber)
                .setSignName(signName)
                .setTemplateCode(withDrawSuccessCode)
                .setTemplateParam(json);
        SendSmsResponse sendSmsResponse = null;
        try {
            sendSmsResponse = client.sendSmsWithOptions(sendSmsRequest,new RuntimeOptions());
        }catch (Exception e){
            throw new RuntimeException(e);
        }
        if ("OK".equals(sendSmsResponse.getBody().getCode())) {
            log.info(phoneNumber+"发送成功");
        }
    }

    @Override
    public void sendWithDrawFailed(Long uid, String time, String message) {
        System.out.println("调用提现失败接口");
        User user = userService.getById(uid);
        String phoneNumber = user.getUserName();
        String signName = aliSmsProperties.getSignName();
        String withDrawFailedCode = aliSmsProperties.getWithDrawFailedCode();
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("time",time);
        paramMap.put("message",message);
        String json = new Gson().toJson(paramMap);
        SendSmsRequest sendSmsRequest = new SendSmsRequest()
                .setPhoneNumbers(phoneNumber)
                .setSignName(signName)
                .setTemplateCode(withDrawFailedCode)
                .setTemplateParam(json);
        SendSmsResponse sendSmsResponse = null;
        try{
            sendSmsResponse = client.sendSmsWithOptions(sendSmsRequest,new RuntimeOptions());
        }catch (Exception e){
            throw new RuntimeException(e);
        }
        System.out.println(sendSmsResponse.getBody().getCode());
        if ("OK".equals(sendSmsResponse.getBody().getCode())){
            log.info(phoneNumber+"发送成功");
        }
    }

    @Override
    public void removeN() {
        List<SystemMessage> systemMessages = systemMessageMapper.selectList(null);
        for(SystemMessage systemMessage : systemMessages){
            Long waybillId = systemMessage.getWaybillId();
            Waybill waybill = wayBillService.getById(waybillId);
            if (waybill == null) {
                QueryWrapper<SystemMessage> wrapper = new QueryWrapper<>();
                wrapper.lambda().eq(SystemMessage::getWaybillId,waybillId);
                systemMessageMapper.delete(wrapper);
            }
        }
    }


}
